package com.blog.utils;

import com.blog.service.UserService;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

@Component
public class SpringUtils implements ApplicationContextAware {
    public static ApplicationContext applicationContext = null;

    public SpringUtils() {
    }

    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }

    public static <T> T getUserServiceBean() {
        return (T) applicationContext.getBean(UserService.class);
    }

    public static <R> R getUserServiceToDo(Function<UserService, R> fun) {
        UserService bean = (UserService)getBean(UserService.class);
        return fun.apply(bean);
    }

    public static <T, R> R getBeanToDoAndReturn(Class<T> clazz, Function<T, R> fun) {
        T bean = getBean(clazz);
        return fun.apply(bean);
    }

    public static <T> void getBeanToDo(Class<T> clazz, Consumer<T> fun) {
        T bean = getBean(clazz);
        fun.accept(bean);
    }

    public static <T> void getBeansToDo(Class<T> clazz, Consumer<T> fun) {
        List<T> beans = getBeanList(clazz);
        beans.forEach(fun);
    }

    public static <T> boolean getBeanToCheck(Class<T> clazz, Predicate<T> pre) {
        T bean = getBean(clazz);
        return pre.test(bean);
    }

    public static <T> T getBean(String beanName, Class<T> clazz) {
        return applicationContext.getBean(beanName, clazz);
    }

    public static <T> Map<String, T> getBeanMap(Class<T> clazz) {
        return applicationContext.getBeansOfType(clazz);
    }

    public static <T> List<T> getBeanList(Class<T> clazz) {
        Map<String, T> beanMap = applicationContext.getBeansOfType(clazz);
        ArrayList<T> beanList = new ArrayList(beanMap.values());
        beanList.sort(AnnotationAwareOrderComparator.INSTANCE);
        return beanList;
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtils.applicationContext = applicationContext;
    }
}
